package com.lightjet.macross.base.feign.api.config;

import lombok.extern.java.Log;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.http.HttpMethod;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;
import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configurers.ResourceServerSecurityConfigurer;
import org.springframework.security.oauth2.provider.token.DefaultTokenServices;
import org.springframework.security.oauth2.provider.token.ResourceServerTokenServices;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter;
import org.springframework.security.oauth2.provider.token.store.redis.RedisTokenStore;
import org.springframework.web.bind.annotation.CrossOrigin;

/**
 * @author : lijia
 * @version : 1.0 2019-10-26 14:02
 * description : 资源服务默认配置
 */
@Configuration
@EnableResourceServer
@EnableGlobalMethodSecurity(prePostEnabled = true)
@Log
public class ResourceConfiguration extends ResourceServerConfigurerAdapter {

    @Value("${security.oauth2.resource.id:macross}")
    private String SOURCE_ID;

    @Autowired
    private RedisConnectionFactory redisConnectionFactory;

    @Override
    @CrossOrigin
    public void configure(ResourceServerSecurityConfigurer resources) {
        resources
                .resourceId(SOURCE_ID)
                .stateless(true);
        resources.tokenServices(defaultTokenServices());
        log.info("注入SourceId:"+SOURCE_ID);
    }

    @Override
    public void configure(HttpSecurity http) throws Exception {
        // @formatter:off
        // 我们这里放开/order/*的请求，以/order/*开头的请求不用认证
        // 由于使用的是JWT，我们这里不需要csrf,不用担心csrf攻击
        http.csrf().disable()
                // 基于token，所以不需要session
                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()

                .authorizeRequests()
                //.antMatchers(HttpMethod.OPTIONS, "/**").permitAll()

                // 允许对于网站静态资源的无授权访问

                .regexMatchers(
                        ".*swagger.*",
                        ".*v2.*",
                        ".*webjars.*",
                        "/csrf",
                        "/",
                        "/favicon.ico",
                        ".*actuator.*",
                        "/modeler.*"
//                        "/js/**",
//                        "/css/**",
//                        "/fonts/**"
                ).permitAll()
//                .antMatchers(
//                        HttpMethod.GET,
//                        "/",
//                        "/*.html",
//                        "/favicon.ico",
//                        "/**/*.html",
//                        "/**/*.css",
//                        "/**/*.js",
//                        "/csrf",
//                        "/webjars/**","/swagger-resources/**",//swagger请求
//                        "/v2/api-docs"
//                ).permitAll()
                // 对于获取token的rest api要允许匿名访问
                .antMatchers(
                        "/auth/**",
                        "/pub/**",
                        "/process/**",
                        "/api/doc/**",
                        "/editor/stencilset",
                        "/diagram-viewer/**",
                        "/editor-app/**",
                        "/model/**",
                        "/images/**").permitAll()
                // 除上面外的所有请求全部需要鉴权认证。 .and() 相当于标示一个标签的结束，之前相当于都是一个标签项下的内容
                .anyRequest().authenticated();
        //.and().addFilterBefore(authenticationTokenFilterBean(), UsernamePasswordAuthenticationFilter.class);

        // 禁用缓存
        http.headers()
                .cacheControl().disable()
                .frameOptions().disable() //允许被潜在Iframe里面
                .httpStrictTransportSecurity().disable();;

        /*http.authorizeRequests().antMatchers(
                "/**",
                "/swagger-ui.html",                                //让他们可以通过spring的加密体系
                "/swagger-resources/**",
                "/v2/api-docs",
                "/webjars/**",
                "/apidoc/**"
        ).permitAll().and().authorizeRequests()
                .antMatchers(HttpMethod.OPTIONS).permitAll() ;//.anyRequest().authenticated();*/
        // @formatter:on
    }

/*    @Bean
    public JwtAuthenticationTokenFilter authenticationTokenFilterBean() throws Exception {
        return new JwtAuthenticationTokenFilter();
    }*/


    // 自定义的Token存储器，存到Redis中
    @Bean
    public TokenStore tokenStore() {
        RedisTokenStore tokenStore = new RedisTokenStore(redisConnectionFactory);
        return tokenStore;
    }

    // Token转换器
    @Bean
    public JwtAccessTokenConverter accessTokenConverter() {
        JwtAccessTokenConverter accessTokenConverter = new JwtAccessTokenConverter() {
        };
        accessTokenConverter.setSigningKey("SigningKey");
        return accessTokenConverter;
    }

    /**
     * 创建一个默认的资源服务token
     */
    @Bean
    public ResourceServerTokenServices defaultTokenServices() {
        final DefaultTokenServices defaultTokenServices = new DefaultTokenServices();
        // 使用自定义的Token转换器
        defaultTokenServices.setTokenEnhancer(accessTokenConverter());
        // 使用自定义的tokenStore
        defaultTokenServices.setTokenStore(tokenStore());
        return defaultTokenServices;
    }

}
